package com.felix.netty.c2.protocol;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;

@Slf4j
public class RedisProtocol {
    public static void main(String[] args) throws InterruptedException {
        String password = "YINSHI9981redis"; // Redis 密码

        NioEventLoopGroup worker = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.group(worker);
        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(new RedisClientHandler(password));  // 添加认证处理器
            }
        });

        // 连接到 Redis 服务
        ChannelFuture channelFuture = bootstrap.connect("192.168.68.168", 6379).sync();
        channelFuture.channel().closeFuture().sync();

        worker.shutdownGracefully();
    }
}

class RedisClientHandler extends ChannelInboundHandlerAdapter {
    private final String password;

    public RedisClientHandler(String password) {
        this.password = password;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 发送 AUTH 命令进行认证
        sendAuthCommand(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        String response = buf.toString(Charset.defaultCharset());

        // 打印认证响应
        if (response.equals("+OK\r\n")) {
            System.out.println("Authentication successful!");

            // 认证成功后，发送 SET 命令
            sendSetCommand(ctx);
        } else if (response.startsWith("-ERR")) {
            System.out.println("Authentication failed: " + response);
        } else {
            // 读取 Redis 响应数据
            System.out.println("Response: " + response);
        }
    }

    private void sendAuthCommand(ChannelHandlerContext ctx) {
        String authCommand = "*2\r\n$4\r\nAUTH\r\n$" + password.length() + "\r\n" + password + "\r\n";
        ByteBuf authBuffer = Unpooled.copiedBuffer(authCommand.getBytes(Charset.defaultCharset()));
        ctx.writeAndFlush(authBuffer);
    }

    byte[] LINE = {13, 10};
    private void sendSetCommand(ChannelHandlerContext ctx) {
        // 构建 SET 命令（键: aaa, 值: bbb）
        ByteBuf buf = ctx.alloc().buffer();
        buf.writeBytes("*3".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("$3".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("set".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("$3".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("aaa".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("$3".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("bbb".getBytes());
        buf.writeBytes(LINE);
        ctx.writeAndFlush(buf);
    }

    private void sendGetCommand(ChannelHandlerContext ctx) {
        // 构建 GET 命令（键: aaa）
        ByteBuf buf = ctx.alloc().buffer();
        buf.writeBytes("*2".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("$3".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("get".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("$3".getBytes());
        buf.writeBytes(LINE);
        buf.writeBytes("aaa".getBytes());
        buf.writeBytes(LINE);
        ctx.writeAndFlush(buf);
    }
}